package com.earthchen.gps.netty;

import com.earthchen.gps.dao.GpsDao;
import com.earthchen.gps.domain.GpsData;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.earthchen.gps.util.DateTimeUtil.getDateFromDateStringAndTimeString;

/**
 * gps数据处理
 *
 * @author: EarthChen
 * @date: 2018/04/28
 */
public class GpsDataHandler extends ChannelInboundHandlerAdapter {


    /**
     * 需要处理所有接收到的数据，所以你重写了 channelRead()
     * 方法。在这个服务器应用程序中，你将数据简单地回送给了远程节点。
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("服务端收到数据");
        String result = (String) msg;

        // 将接收到的消息写给发送者，而不冲刷出站消息
        System.out.println(result);

        List<String[]> dataList = getDataListFormMsg(result);
        saveGpsDataFromDataList(dataList);

        String response = "success";
        // 在当前场景下，发送的数据必须转换成ByteBuf数组
        ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
        encoded.writeBytes(response.getBytes());
        ctx.write(encoded);
        ctx.flush();
        //ctx.write(result);
    }

    /**
     * 允许你对 Throwable 的任何子类型做出反应， 在这里你
     * 记录了异常并关闭了连接。虽然一个更加完善的应用程序也许会尝试从异常中恢复，但在这个场
     * 景下，只是通过简单地关闭连接来通知远程节点发生了错误。
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }


    /**
     * 解析数据返回数据列表
     *
     * @return
     */
    private List<String[]> getDataListFormMsg(String msg) {
        System.out.println("开始处理");
        List<String[]> list = new ArrayList<>();
        // 根据]切割字符串
        String[] resList = msg.split("]");
        for (String res : resList) {
            // 将左字符串切除
            res = res.substring(1);
            // 根据逗号切割字符串获取每个字段的数据
            String[] dataList = res.split(",");
            list.add(dataList);
        }
        return list;
    }

    /**
     * 根据数据列表获取gps数据对象
     * <p>
     * 短长度的数据长度测试为4，但是为了保证兼容这里使用10来判断
     *
     * @param dataList
     * @return
     */
    public void saveGpsDataFromDataList(List<String[]> dataList) {
        for (String[] data : dataList) {
            System.out.println("字符串长度为" + data.length);
            if (data.length > 10) {
                GpsData gpsData = getGpsDataFromStringList(data);
                if (gpsData != null) {
                    boolean success = saveGpsData(gpsData);
                    if (success) {
                        System.out.println("保存gps数据成功" + gpsData.toString());
                    } else {
                        System.out.println("保存gps失败");
                    }
                }
            }

        }
    }

    /**
     * 保存gps数据
     *
     * @param gpsData
     * @return
     */
    private boolean saveGpsData(GpsData gpsData) {
        return GpsDao.saveGpsData(gpsData);
    }

    /**
     * 根据字符串列表获取gps数据
     *
     * @param dataList
     * @return
     */
    private GpsData getGpsDataFromStringList(String[] dataList) {
        GpsData gpsData = new GpsData();
        gpsData.setSn(dataList[0].split("\\*")[1]);

        // 获取date
        String dateString = dataList[1];
        // 获取time
        String timeString = dataList[2];
        // 构造数据时间
        Date createTime = getDateFromDateStringAndTimeString(dateString, timeString);

        gpsData.setCreateTime(createTime);
        gpsData.setIsLocation(dataList[3]);
        gpsData.setLatitude(dataList[4]);
        gpsData.setLatitudeFlag(dataList[5]);
        gpsData.setLongitude(dataList[6]);
        gpsData.setLongitudeFlag(dataList[7]);
        gpsData.setSpeed(Double.parseDouble(dataList[8]));
        gpsData.setDirection(Double.parseDouble(dataList[9]));
        gpsData.setAltitude(Double.parseDouble(dataList[10]));
        gpsData.setSatelliteNumber(Integer.parseInt(dataList[11]));
        gpsData.setGmsSignalIntensity(Integer.parseInt(dataList[12]));
        gpsData.setPower(Integer.parseInt(dataList[13]));
        gpsData.setStepNumber(Integer.parseInt(dataList[14]));
        gpsData.setRollNumber(Integer.parseInt(dataList[15]));
        gpsData.setTerminalStatus(dataList[16]);
        return gpsData;
    }
}
